package com.lingtianyu.tech.erbaoshen.core.util.serialize;

import com.caucho.hessian.io.Hessian2Input;
import com.caucho.hessian.io.Hessian2Output;
import lombok.extern.slf4j.Slf4j;

import java.io.ByteArrayInputStream;
import java.io.ByteArrayOutputStream;
import java.io.IOException;
import java.lang.reflect.Type;
import java.math.BigDecimal;
import java.util.Base64;
import java.util.Date;

@Slf4j
public class Hessian2SerializeExecute implements SerializeExecute {
    @Override
    public Object unSerializeArray(Object param, Type type) {
       return unSerialize(param);
    }

    @Override
    public String unSerializeString(Object param) {
        return (String) unSerialize(param);
    }

    @Override
    public Date unSerializeDate(Object param) {
        return (Date) unSerialize(param);
    }

    @Override
    public Boolean unSerializeBoolean(Object param) {
        return (Boolean) unSerialize(param);
    }

    @Override
    public Character unSerializeChar(Object param) {
        return unSerialize(param).toString().toCharArray()[0];
    }

    @Override
    public Byte unSerializeByte(Object param) {
        return (Byte) unSerialize(param);
    }

    @Override
    public Short unSerializeShort(Object param) {
        return (Short) unSerialize(param);
    }

    @Override
    public Integer unSerializeInt(Object param) {
        return (Integer) unSerialize(param);
    }

    @Override
    public Long unSerializeLong(Object param) {
        return (Long) unSerialize(param);
    }

    @Override
    public Float unSerializeFloat(Object param) {
        return (Float) unSerialize(param);
    }

    @Override
    public Double unSerializeDouble(Object param) {
        return (Double) unSerialize(param);
    }

    @Override
    public BigDecimal unSerializeBigDecimal(Object param) {
        return (BigDecimal) unSerialize(param);
    }

    @Override
    public Object unSerializeObject(Object param, Type type) {
        return unSerialize(param);
    }

    @Override
    public Object unSerializeDefault(Object param, Type type) {
        return unSerialize(param);
    }

    @Override
    public String serializeParam(Object param) {
        ByteArrayOutputStream byteArrayOutputStream = null;
        Hessian2Output hessian2Output = null;
        try {
            byteArrayOutputStream = new ByteArrayOutputStream();
            hessian2Output = new Hessian2Output(byteArrayOutputStream);
            hessian2Output.writeObject(param);
            hessian2Output.flush();
            byte[] byteArray = byteArrayOutputStream.toByteArray();
            byteArrayOutputStream.close();
            return Base64.getMimeEncoder().encodeToString(byteArray);
        } catch (IOException e) {
            log.error(e.getMessage(), e);
            throw new RuntimeException(e);
        } finally {
            if (hessian2Output != null) {
                try {
                    hessian2Output.close();
                } catch (IOException e) {
                    log.error(e.getMessage(), e);
                }
            }
            if (byteArrayOutputStream != null) {
                try {
                    byteArrayOutputStream.close();
                } catch (IOException e) {
                    log.error(e.getMessage(), e);
                }
            }
        }
    }

    private Object unSerialize(Object param) {
        String s = param.toString();
        ByteArrayInputStream byteArrayInputStream = new ByteArrayInputStream(Base64.getMimeDecoder().decode(s));
        Hessian2Input hessian2Input = null;
        try {
            hessian2Input = new Hessian2Input(byteArrayInputStream);
            return hessian2Input.readObject();
        } catch (IOException e) {
            log.error(e.getMessage(), e);
            throw new RuntimeException(e);
        } finally {
            if(byteArrayInputStream != null) {
                try {
                    byteArrayInputStream.close();
                } catch (IOException e) {
                    log.error(e.getMessage(), e);
                }
            }
            if (hessian2Input != null) {
                try {
                    hessian2Input.close();
                } catch (IOException e) {
                    log.error(e.getMessage(), e);
                }
            }
        }
    }

    @Override
    public String getType() {
        return "hessian2";
    }

    public static void main(String[] args) {
//        Character c = new Hessian2SerializeExecute().unSerializeChar("AWM=");
//        System.out.println(c);
        ByteArrayOutputStream byteArrayOutputStream = new ByteArrayOutputStream();
        Hessian2Output hessian2Output = new Hessian2Output(byteArrayOutputStream);
        Character ss = 'c';
        try {
            hessian2Output.writeObject(ss);
            hessian2Output.flush();
            hessian2Output.close();
            byte[] byteArray = byteArrayOutputStream.toByteArray();
            byteArrayOutputStream.close();
            String s = Base64.getMimeEncoder().encodeToString(byteArray);
            System.out.println(s);

            ByteArrayInputStream byteArrayInputStream = new ByteArrayInputStream(Base64.getMimeDecoder().decode(s));
            Hessian2Input hessian2Input = new Hessian2Input(byteArrayInputStream);
            Object o = hessian2Input.readObject();
            System.out.println((char)o);
            hessian2Input.close();
            byteArrayInputStream.close();
        } catch (IOException e) {
            throw new RuntimeException(e);
        }
    }
}
